package com.fruit.service.order.impl;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.fruit.constants.GoodsContant;
import com.fruit.constants.OrderConstant;
import com.fruit.constants.PayConstant;
import com.fruit.constants.SysMessageConstant;
import com.fruit.mapper.order.OrderMapper;
import com.fruit.mapper.pay.PayMapper;
import com.fruit.pojo.order.DSHOrder;
import com.fruit.pojo.order.Order;
import com.fruit.pojo.order.OrderConfig;
import com.fruit.pojo.order.OrderGoods;
import com.fruit.pojo.pay.TransactionFlow;
import com.fruit.pojo.rights.UserGoodsRights;
import com.fruit.pojo.user.sysmsg.SysMessage;
import com.fruit.sdk.account.commission.CommissionBackService;
import com.fruit.service.order.DelayHandel;
import com.fruit.service.order.OrderManager;
import com.fruit.service.redis.JedisUtil;
import com.fruit.service.rights.UserRightsManager;
import com.fruit.service.sysmsg.SysMessageService;
import com.fruit.util.DateUtil;
import com.fruit.util.ResultInfo;
import com.fruit.util.ResultUtil;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class OrderService implements OrderManager{
	
	@Autowired
	private OrderMapper orderMapper;
	
	@Autowired
	private PayMapper payMapper;
	
	@Value("${domain}")
	private String domain;
	
	@Autowired
    private JedisUtil jedisService;
	
	@Autowired
	private DelayHandel delayService;
	
	@Autowired
	private UserRightsManager userRightsService;
	
	@Autowired
	private CommissionBackService commissionBackService;
	
	@Autowired
	private OrderLogService orderLogService;
	
	@Autowired
	private SysMessageService sysMessageService;
	
	@Override
	public Map<String, Object> updateOrderState(String tradeId, TransactionFlow tf) {
		Map<String, Object> resMap = new HashMap<String, Object>();
		log.info("[{}]-【处理业务订单】-【开始】",tradeId);
		Order order = null;
		String serviceState = null;
		try{
			order = orderMapper.getOrderByTransactionId(tf.getId());
			if(order == null){
				//异常处理
				resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "order_null", "订单不存在!"));
				serviceState = OrderConstant.ServiceState.updateOrder.getValue();
				return resMap;
			}
			log.info("[{}]-【处理业务订单】-【订单号：{}】",tradeId,order.getCode());
			if(!OrderConstant.State.notpay.equals(order.getState())){
				resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "order_error", "订单状态更新失败!",null,ResultInfo.ROLLBACK));
				serviceState = OrderConstant.ServiceState.updateOrder.getValue();
				return resMap;
			}
			
			try{
				log.info("[{}]-【处理业务订单】-【从取消队列移除订单】",tradeId);
				//从队列删除
				delayService.remove(order.getId());
				//从redis删除
				jedisService.hdel(OrderConstant.ORDER_AUTO_CANCEL, order.getId()+"");
			}catch(Exception e){
				e.printStackTrace();
				//异常处理
				log.info("[{}]-【处理业务订单】-【从取消队列移除订单】-【异常】----{}",tradeId,getStackTraceAsString(e));
			}
			
			order.setState(OrderConstant.State.pay.getValue());
			log.info("[{}]-【处理业务订单】-【更新订单状态】",tradeId);
			int num = orderMapper.updateOrderStateById(order);
			if(num == 0){
				//异常处理
				log.error("[{}]-【处理业务订单】-【更新订单状态】-【失败】",tradeId);
				resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "order_update_fail", "订单状态更新失败!"));
				serviceState = OrderConstant.ServiceState.updateOrder.getValue();
				return resMap;
			}
			log.info("[{}]-【处理业务订单】-【更新订单状态】-【成功】",tradeId);	
			
			
			log.info("[{}]-【处理业务订单】-【更新果树绑定状态】",tradeId);
			//绑定果树
			List<OrderGoods> ogList = orderMapper.getOrderGoodsByOrderId(order.getId());
			Map<String, Object> params = new HashMap<String, Object>();
			StringBuffer sysMessage = new StringBuffer();
			for(OrderGoods og:ogList){
				log.info("[{}]-【处理业务订单】-【更新库存】-【商品规格期次ID：{}】",tradeId,og.getGoodsSpecTimeId());
				num = payMapper.updateGoodsSpecTimeSaleNum(og);
				if(num == 0){
					log.error("[{}]-【处理业务订单】-【更新库存】-【失败】",tradeId);
					resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "update_sale_num", "更新已售数量失败",null,ResultInfo.ROLLBACK));
					serviceState = OrderConstant.ServiceState.updateFruit.getValue();
				}
				
				log.info("[{}]-【处理业务订单】-【更新库存】-【成功】",tradeId);
				
				String[] areaGoodsInfoIdsArray = StringUtils.split(og.getAreaGoodsInfoIds(),"|");
				if(areaGoodsInfoIdsArray == null || areaGoodsInfoIdsArray.length == 0){
					//异常处理
					resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "binding_fail", "绑定失败",null,ResultInfo.ROLLBACK));
					serviceState = OrderConstant.ServiceState.updateFruit.getValue();
					return resMap;
				}
				for(String areaGoodsInfoIds : areaGoodsInfoIdsArray){
					int idsNum = StringUtils.split(areaGoodsInfoIds,",").length;
					params.clear();
					params.put("isBinding", GoodsContant.Binding.YES.getValue());
					params.put("areaGoodsInfoIds", areaGoodsInfoIds);
					params.put("userId", order.getUserId());
					params.put("endUseTime", og.getEndUseTime());
					num = payMapper.updateAreaGoodsNotUserBinding(params);
					if(idsNum != num){
						//异常处理
						resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "binding_fail", "绑定失败",null,ResultInfo.ROLLBACK));
						serviceState = OrderConstant.ServiceState.updateFruit.getValue();
						return resMap;
					}
				}
				sysMessage.append(og.getNumber()).append(og.getUnitDesc()).append(og.getTitle()).append(",");
			}
			log.info("[{}]-【处理业务订单】-【更新果树绑定状态】-【成功】",tradeId);
			
			//1、处理我的权益
			saveGoodsRight(tradeId, ogList,tf);
			
			//2、计算佣金
			insertCommBack(tradeId, tf);
			
			//3、发送站内信
			insertSysMsg(sysMessage, tf.getUserId(),tradeId);
			
			resMap.put("result", ResultUtil.initResult(ResultInfo.SUCCESS, "ok", "更新成功!"));
			
			return resMap;
		}catch(Exception e){
			e.printStackTrace();
			//异常处理
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "exception", "系统异常!",null,ResultInfo.ROLLBACK));
			resMap.put("serviceState",OrderConstant.ServiceState.updateOrder.getValue());
			return resMap;
		}finally{
			ResultInfo ri = (ResultInfo)resMap.get("result");
			if(ResultInfo.ROLLBACK.equals(ri.getIsRollBack())){
				TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			}
			if(ResultInfo.ERROR.equals(ri.getState())){
				log.error("[{}]-【处理业务订单】-【异常】-【{}：{}】",tradeId,ri.getCode(),ri.getMessage());
				if(order != null){
					//插入错误日志
					orderLogService.newSaveExceptionOrder(tradeId, "OrderService", serviceState,
							order.getCode(), order.getUserId(), ri.getCode(),ri.getMessage());
				}
			}else{
				log.info("[{}]-【处理业务订单】-【成功】",tradeId);
			}
			log.info("[{}]-【处理业务订单】-【成功】",tradeId);
		}


	}
	
	public void insertSysMsg(StringBuffer sysMessage,int userId, String tradeId){
		log.info("[{}]-【处理业务订单】-【发送站内信】",tradeId);
		try{
		SysMessage record = new SysMessage();
		record.setTitle("认养成功");
		record.setContent("恭喜您认养了"+sysMessage.substring(0, sysMessage.length()-1));
		record.setUserId(userId);
		record.setType(SysMessageConstant.Type.buySuccess.getValue());
		record.setState(SysMessageConstant.State.no.getValue());
		record.setCreateTime(DateUtil.getTime());
		record.setUpdateTime(record.getCreateTime());
		record.setMsgType(SysMessageConstant.MsgType.notice.getValue());
		sysMessageService.insert(record);
		}catch(Exception e){
			log.error("[{}]-【处理业务订单】-【发送站内信】-【异常】----{}",tradeId,getStackTraceAsString(e));
		}
		log.info("[{}]-【处理业务订单】-【发送站内信】-【结束】",tradeId);
	}
	
	//计算佣金
	public void insertCommBack(String tradeId, TransactionFlow tf){
		log.info("[{}]-【处理业务订单】-【处理佣金】",tradeId);
		try{
		Map<String,Object> resMap = commissionBackService.insertCommBack(tradeId,tf.getUserId(), tf.getPayPrice());
		ResultInfo ri = (ResultInfo) resMap.get("result");
		if(ResultInfo.ERROR.equals(ri.getState())){
			log.error("[{}]-【处理业务订单】-【处理佣金】-【异常】-【{}:{}】",tradeId,"handelCommBackError","处理佣金失败");
			orderLogService.newSaveExceptionOrder(tradeId, "OrderService", OrderConstant.ServiceState.handelCommission.getValue(),
					tf.getCode(), tf.getUserId(), "handelCommBackError","处理佣金失败");
			
		}else{
			log.info("[{}]-【处理业务订单】-【处理佣金】-【成功】",tradeId);
		}
		}catch(Exception e){
			log.error("[{}]-【处理业务订单】-【处理佣金】-【异常】----{}",tradeId,getStackTraceAsString(e));
			orderLogService.newSaveExceptionOrder(tradeId, "OrderService", OrderConstant.ServiceState.handelCommission.getValue(),
					tf.getCode(), tf.getUserId(), "handelCommBackException","处理佣金异常");
		}
		log.info("[{}]-【处理业务订单】-【处理佣金】-【结束】",tradeId);
	}
	
	
	//处理我的权益
	public void saveGoodsRight(String tradeId, List<OrderGoods> ogList, TransactionFlow tf){
		log.info("[{}]-【处理业务订单】-【处理我的权益】",tradeId);
		try{
		//插入我的权益
		String curTime = DateUtil.getTime();
		List<UserGoodsRights> ugrList = new ArrayList<UserGoodsRights>();
		log.info("[{}]-【处理业务订单】-【处理我的权益】-【封装权益参数】",tradeId);
		for(OrderGoods og:ogList){
			UserGoodsRights ugr = new UserGoodsRights();
			ugr.setOrderGoodsId(og.getId());
			ugr.setBaseId(og.getBaseId());
			ugr.setBaseName(og.getBaseName());
			ugr.setClassId(og.getClassId());
			ugr.setGoodsSpecTimeId(og.getGoodsSpecTimeId());
			ugr.setGoodsName(og.getTitle());
			ugr.setThumb(og.getGoodsThumb());
			ugr.setThumbDay(og.getThumbDay());
			ugr.setThumbNight(og.getThumbNight());
			ugr.setUserId(og.getUserId());
			ugr.setTime(og.getTime());
			ugr.setExpectHarvests(og.getExpectHarvests());
			ugr.setExpectHarvestTimes(og.getHarvestTimes());
			ugr.setFruitPeriod(og.getFruitPeriod());
			ugr.setEquityCycle(og.getEquityCycle());
			ugr.setBirthday(og.getBirthday());
			ugr.setBuyTime(og.getBuyTime());
			ugr.setEndUseTime(og.getEndUseTime());
			ugr.setBuyTime(curTime);
			ugr.setNum(og.getNumber());
			ugr.setUnit(og.getUnit());
			ugr.setHarvestUnit(og.getHarvestUnit());
			ugr.setAreaGoodsInfoIds(og.getAreaGoodsInfoIds());
			ugr.setCreateTime(DateUtil.getTime());
			ugr.setUpdateTime(ugr.getCreateTime());
			ugrList.add(ugr);
			
		}
		Map<String,Object> resMap = userRightsService.insertGoodsRight(ugrList,tradeId);
		ResultInfo ri = (ResultInfo) resMap.get("result");
		if(ResultInfo.ERROR.equals(ri.getState())){
			log.error("[{}]-【处理业务订单】-【处理我的权益】-【异常】-【{}:{}】",tradeId,"handelRightError","处理权益失败");
			orderLogService.newSaveExceptionOrder(tradeId, "OrderService", OrderConstant.ServiceState.handelRights.getValue(),
					tf.getCode(), tf.getUserId(), "handelRightError","处理权益失败");
			
		}else{
			log.info("[{}]-【处理业务订单】-【处理我的权益】-【成功】",tradeId);
		}
		
		}catch(Exception e){
			e.printStackTrace();
			//异常处理
			log.error("[{}]-【处理业务订单】-【处理我的权益】-【异常】----{}",tradeId,getStackTraceAsString(e));
			orderLogService.newSaveExceptionOrder(tradeId, "OrderService", OrderConstant.ServiceState.handelRights.getValue(),
					tf.getCode(), tf.getUserId(), "handelRightException","处理权益异常");
		}
		log.info("[{}]-【处理业务订单】-【处理我的权益】-【结束】",tradeId);
	}
	
	public String getStackTraceAsString(Throwable ex) {
		StringWriter stringWriter = new StringWriter();
		ex.printStackTrace(new PrintWriter(stringWriter));
		return stringWriter.toString();
	}
	
	@Override
	public Map<String, Object> updateAutoCancelOrder(String tradeId,Order o, DSHOrder dshOrder) {
		Map<String, Object> resMap = new HashMap<String, Object>();
		log.info("[{}]-【取消订单】-【业务处理】-【订单ID：{}】",tradeId,dshOrder.getOrderId());
		try{
			
			Order order = orderMapper.getOrderById(dshOrder.getOrderId());
			
			//判断订单是否存在
			log.info("[{}]-【取消订单】-【判断订单是否存在】",tradeId);
			if(order == null){
				resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "order_not_exists", "订单不存在!"));
				jedisService.hdel(OrderConstant.ORDER_AUTO_CANCEL, dshOrder.getOrderId()+"");
				resMap.put("serviceState", OrderConstant.ServiceState.cancelUpdateOrder.getValue());
				return resMap;
			}
			o.setCode(order.getCode());
			o.setUserId(order.getUserId());
			//判断订单支付类型
			log.info("[{}]-【取消订单】-【判断订单状态】",tradeId);
			if(!OrderConstant.State.notpay.equals(order.getState())){
				resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "order_state_error", "订单状态不正确!"));
				jedisService.hdel(OrderConstant.ORDER_AUTO_CANCEL, dshOrder.getOrderId()+"");
				resMap.put("serviceState", OrderConstant.ServiceState.cancelUpdateOrder.getValue());
				return resMap;
			}
			order.setState(OrderConstant.State.cancel.getValue());
			log.info("[{}]-【取消订单】-【更新订单状态】",tradeId);
			int num = orderMapper.updateOrderStateById(order);
			if(num == 0){
				resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "again_start", "订单状态取消失败!",null,ResultInfo.ROLLBACK));
				resMap.put("serviceState", OrderConstant.ServiceState.cancelUpdateOrder.getValue());
				return resMap;
			}
			
			//更新账单状态
			log.info("[{}]-【取消订单】-【判断账单是否存在】",tradeId);
			TransactionFlow tf = payMapper.getTransactionFlowById(order.getTransactionId());
			if(tf == null){
				resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "transaction_not_exists", "账单不存在!"));
				jedisService.hdel(OrderConstant.ORDER_AUTO_CANCEL, dshOrder.getOrderId()+"");
				resMap.put("serviceState", OrderConstant.ServiceState.cancelUpdateOrder.getValue());
				return resMap;
			}
			log.info("[{}]-【取消订单】-【判断账单状态】",tradeId);
			if(!PayConstant.State.notpay.equals(tf.getState())){
				resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "transaction_state_error", "账单状态不正确!"));
				jedisService.hdel(OrderConstant.ORDER_AUTO_CANCEL, dshOrder.getOrderId()+"");
				resMap.put("serviceState", OrderConstant.ServiceState.cancelUpdateOrder.getValue());
				return resMap;
			}
			
			tf.setState(PayConstant.State.cancel.getValue());
			tf.setFinishTime(DateUtil.getTime());
			
			log.info("[{}]-【取消订单】-【更新账单状态】",tradeId);
			num = payMapper.updateTransactionFlowState(tf);
			if(num == 0){
				resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "again_start", "账单状态取消失败!",null,ResultInfo.ROLLBACK));
				resMap.put("serviceState", OrderConstant.ServiceState.cancelUpdateOrder.getValue());
				return resMap;
			}
			
			//修改商品库存
			log.info("[{}]-【取消订单】-【更新商品库存】",tradeId);
			List<OrderGoods> ogList = orderMapper.getOrderGoodsByOrderId(order.getId());
			Map<String, Object> params = new HashMap<String, Object>();
			for(OrderGoods og:ogList){
				log.info("[{}]-【取消订单】-【更新商品期次库存】-【商品期次ID：{}】",tradeId,og.getGoodsSpecTimeId());
				params.clear();
				params.put("id", og.getGoodsSpecTimeId());
				params.put("num", og.getNumber());
				num = payMapper.updateAddGoodsSpecTimeStockNum(params);
				if(num == 0){
					//异常处理
					resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "again_start","商品期次库存更新失败", null,ResultInfo.ROLLBACK));
					resMap.put("serviceState", OrderConstant.ServiceState.cancelUpdateFruit.getValue());
					return resMap;
				}
				log.info("[{}]-【取消订单】-【更新商品区域库存】-【商品区域ID：{}】",tradeId,og.getAreaGoodsCountId());
				params.clear();
				params.put("id", og.getAreaGoodsCountId());
				params.put("takeNum", og.getNumber());
				params.put("takeState", "min");
				num = payMapper.updateAreaGoodsTakeNumByMap(params);
				if(num == 0){
					//异常处理
					resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "again_start", "商品区域库存更新失败",null,ResultInfo.ROLLBACK));
					resMap.put("serviceState", OrderConstant.ServiceState.cancelUpdateFruit.getValue());
					return resMap;
				}
				String[] areaGoodsInfoIdsArray = StringUtils.split(og.getAreaGoodsInfoIds(),"|");
				if(areaGoodsInfoIdsArray == null || areaGoodsInfoIdsArray.length == 0){
					//异常处理
					resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "again_start", "果树解绑失败",null,ResultInfo.ROLLBACK));
					resMap.put("serviceState", OrderConstant.ServiceState.cancelUpdateFruit.getValue());
					return resMap;
				}
				for(String areaGoodsInfoIds : areaGoodsInfoIdsArray){
					int idsNum = StringUtils.split(areaGoodsInfoIds,",").length;
					params.clear();
					params.put("isBinding", GoodsContant.Binding.NO.getValue());
					params.put("areaGoodsInfoIds", areaGoodsInfoIds);
					num = payMapper.updateAreaGoodsNotUserBinding(params);
					if(idsNum != num){
						//异常处理
						resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "again_start", "果树解绑失败",null,ResultInfo.ROLLBACK));
						resMap.put("serviceState", OrderConstant.ServiceState.cancelUpdateFruit.getValue());
						return resMap;
					}
				}
				
				
			}	
			jedisService.hdel(OrderConstant.ORDER_AUTO_CANCEL, dshOrder.getOrderId()+"");
			resMap.put("result", ResultUtil.initResult(ResultInfo.SUCCESS, "ok", "取消成功!"));
			return resMap;
		}catch(Exception e){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "exception", "系统异常!",null,ResultInfo.ROLLBACK));
			resMap.put("serviceState", OrderConstant.ServiceState.cancelUpdateOrder.getValue());
			return resMap;
		}finally{
			ResultInfo ri = (ResultInfo)resMap.get("result");
			if(ResultInfo.ROLLBACK.equals(ri.getIsRollBack())){
				TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			}
		}
	}

	
	@Override
	public void saveAutoCancelOrder(long orderId) {
		int timeOut = 900;
		List<OrderConfig> oc = orderMapper.getOrderConfig();
		if(oc != null && oc.size() == 1){
				timeOut = oc.get(0).getAutoCancelTime();
		}	
			
		DSHOrder order = new DSHOrder(orderId,timeOut);
		//插入待取消队列
		delayService.add(order);
		
		//插入redis
		jedisService.hset(OrderConstant.ORDER_AUTO_CANCEL, orderId+"", order.getStartTime()+"");
		
	}

	@Override
	public void newSaveAutoCancelOrder(long orderId) {
		try{
		int timeOut = 900;
		List<OrderConfig> oc = orderMapper.getOrderConfig();
		if(oc != null && oc.size() == 1){
				timeOut = oc.get(0).getAutoCancelTime();
		}	
			
		DSHOrder order = new DSHOrder(orderId,timeOut);
		//插入待取消队列
		delayService.add(order);
		
		//插入redis
		jedisService.hset(OrderConstant.ORDER_AUTO_CANCEL, orderId+"", order.getStartTime()+"");
		}catch(Exception e){
			e.printStackTrace();
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
		}
		
	}

	
}
